package cn.zhejianglao.shirotemplate.service.user.service;

import cn.zhejianglao.shirotemplate.common.CommonUtils;
import cn.zhejianglao.shirotemplate.common.model.UserRoleGetOutDTO;
import cn.zhejianglao.shirotemplate.common.model.UserRoleVO;
import cn.zhejianglao.shirotemplate.common.model.UserVO;
import cn.zhejianglao.shirotemplate.service.role.dao.IRoleMapper;
import cn.zhejianglao.shirotemplate.utils.EncryptUtils;
import cn.zhejianglao.shirotemplate.common.model.Response;
import cn.zhejianglao.shirotemplate.service.user.model.CreateUserRequest;
import cn.zhejianglao.shirotemplate.service.user.model.LoginRequest;
import cn.zhejianglao.shirotemplate.service.user.model.UserGetOutDTO;
import cn.zhejianglao.shirotemplate.constant.ConstantProperties;
import cn.zhejianglao.shirotemplate.exception.BusinessException;
import cn.zhejianglao.shirotemplate.exception.ExceptionCode;
import com.alibaba.fastjson.JSON;
import cn.zhejianglao.shirotemplate.service.user.dao.IUserMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 用户服务实现类
 *
 * @since 2024/1/7
 */
@Service
public class UserService implements IUserService {

    @Autowired
    private IUserMapper userMapper;

    @Autowired
    private IRoleMapper roleMapper;

    @Autowired
    private ConstantProperties properties;

    @Override
    public void setCurrentUser(UserGetOutDTO userGetOutDTO) {
        SecurityUtils.getSubject().getSession()
                .setAttribute(properties.getCurrentUser(), JSON.toJSONString(userGetOutDTO));
    }

    @Override
    public UserGetOutDTO getCurrentUser() {
        return JSON.parseObject(
                SecurityUtils.getSubject().getSession().getAttribute(properties.getCurrentUser()).toString(),
                UserGetOutDTO.class);
    }

    @Override
    public void login(LoginRequest request) {
        Subject subject = SecurityUtils.getSubject();
        subject.login(new UsernamePasswordToken(request.getUsername(), EncryptUtils.hashStr(request.getPassword())));
        subject.getSession().setTimeout(properties.getPermissionSessionTimeout());
        setSessionUser(request.getUsername());
    }

    /**
     * 设置会话用户
     *
     * @param username 用户名
     */
    private void setSessionUser(String username) {
        UserVO userVO = userMapper.selectByUsername(username);
        UserGetOutDTO userGetOutDTO = new UserGetOutDTO();
        userGetOutDTO.setId(userVO.getId());
        userGetOutDTO.setUsername(userVO.getUsername());
        userGetOutDTO.setName(userVO.getName());
        userGetOutDTO.setCurrentRoleId(userVO.getCurrentRoleId());
        setCurrentUser(userGetOutDTO);
    }

    @Override
    public String create(CreateUserRequest request) {
        int count = userMapper.selectCountByUsername(request.getUsername());
        if (count > 0) {
            throw new BusinessException(
                    ExceptionCode.Permission.USER_ALREADY_EXISTS_CODE,
                    ExceptionCode.Permission.USER_ALREADY_EXISTS_MSG
            );
        }
        String hashedPassword = EncryptUtils.hashStr(request.getPassword());
        UserVO userVO = new UserVO();
        userVO.setUsername(request.getUsername());
        userVO.setName(request.getName());
        userVO.setPassword(hashedPassword);
        userVO.setCreatedBy(getCurrentUser().getId());
        userVO.setNamePinyin(CommonUtils.getPinyin(request.getName()));
        userMapper.insert(userVO);
        return Response.SUCCESS_MESSAGE;
    }

    @Override
    public List<UserRoleGetOutDTO> getRoles() {
        Long currentUserId = getCurrentUser().getId();
        return roleMapper.selectByUserId(currentUserId);
    }

    @Transactional
    @Override
    public void switchRole(Long roleId) {
        Long currentUserId = getCurrentUser().getId();
        UserRoleVO userRoleVO = new UserRoleVO();
        userRoleVO.setUserId(currentUserId);
        userRoleVO.setRoleId(roleId);
        if (roleMapper.selectCountByRelation(userRoleVO) == 0) {
            throw new BusinessException(
                    ExceptionCode.Permission.INSUFFICIENT_PERMISSION_CODE,
                    ExceptionCode.Permission.INSUFFICIENT_PERMISSION_MSG
            );
        }
        userMapper.updateCurrentRoleIdByUserId(roleId, currentUserId);
        String roleName = roleMapper.selectById(roleId).getRoleName();
        Subject subject = SecurityUtils.getSubject();
        subject.hasRole(roleName);  // 触发重新加载角色、权限信息
        setSessionUser(getCurrentUser().getUsername());
    }

    @Override
    public void rename(String newName) {
        Long userId = getCurrentUser().getId();
        UserVO userVO = userMapper.selectById(userId);
        if (userVO == null || newName.equals(userVO.getName())) {
            return;
        }
        UserVO updateUserVO = new UserVO();
        updateUserVO.setId(userId);
        updateUserVO.setModifiedBy(userId);
        updateUserVO.setName(newName);
        updateUserVO.setNamePinyin(CommonUtils.getPinyin(newName));
        userMapper.update(updateUserVO);
    }

    @Transactional
    @Override
    public void delete(Long userId) {
        UserVO userVO = userMapper.selectById(userId);
        if (userVO == null) {
            return;
        }
        Long currentUserId = getCurrentUser().getId();
        if (currentUserId != null && currentUserId.compareTo(userId) == 0) {
            throw new BusinessException(ExceptionCode.Permission.INSUFFICIENT_PERMISSION_CODE, "不可以删除自己");
        }
        // 删除绑定的角色
        roleMapper.deleteUserRoleRelationByUserId(userId);
        // 删除用户
        userMapper.deleteById(userId);
    }
}
